import os
import threading
from sensor.sensor import Sensor
from sensor.fakeSensor import FakeSensor
from sensor.realSensor import RealSensor
from observation.observation import Observation
from observation.fakeObservation import FakeObservation
from fileOP.fileOP import FileOP
from fileOP.fileIO import FileIO
from datetime import datetime
import json


class Recoder:
    def __init__(
        self,
        sensor: Sensor,
        op: FileOP,
        tag: str = "undefined",
        obs: Observation = None,
    ):
        self.sensor = sensor
        self.op = op
        self.obs = obs
        self.io = FileIO(op)
        self.tag = tag
        self.quit = False

    def StartRecord(self):
        self.sensor.Open()
        while not self.quit:
            print(f"[{self.tag}]Record start at: {datetime.now()}")
            name = self.op.GetFileName(datetime.now())

            datas = []
            minute = datetime.now().minute
            while datetime.now().minute == minute:
                data = self.sensor.Read()
                if data is None:
                    continue
                datas.append(data)
                print(f"[{self.tag}]Received:[{data.CodeToString()}]")

            rawPath = self.op.GetAbsFilePath(name, "raw", ".csv")
            rawIO = FileIO(rawPath)
            messages = []
            for data in datas:
                messages.append(data.CodeToString())
            rawIO.WriteTexts(messages)
            print(f"[{self.tag}]Record raw data finished and saved at: {rawPath}")

            if self.obs is not None:
                self.obs.CheckErrorMessages(datas)
                postPath = self.op.GetAbsFilePath(name, "post", ".csv")
                postIO = FileIO(postPath)
                messages.clear()
                for data in datas:
                    messages.append(data.CodeToString())
                postIO.WriteTexts(messages)
                print(
                    f"[{self.tag}]Record post data finished and saved at: {postPath}")

    def StopRecord(self):
        self.sensor.Close()

if __name__ == "__main__":
    threads = []
    with open("configs/test.json", "r") as f:
        config = json.load(f)
    sensorCfgs = config["sensor"]
    obs = FakeObservation()
    recorders: list[Recoder] = []
    for sensorCfg in sensorCfgs:
        op = FileOP(os.path.join(config["dataDir"], sensorCfg["name"]))
        if sensorCfg["type"] == "fake":
            sensor = FakeSensor(sensorCfg["interval"])
            recorders.append(Recoder(sensor, op, sensorCfg["name"], obs))
        elif sensorCfg["type"] == "real":
            sensor = RealSensor(sensorCfg["com"], sensorCfg["baudrate"])
            recorders.append(Recoder(sensor, op, sensorCfg["name"], obs))
        else:
            print("Invalid sensor type.") 
    for recorder in recorders:
        threads.append(threading.Thread(target=recorder.StartRecord))
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()
    print("main thread quit.")
